package com.boomcat.boomcat.config;

import com.alibaba.fastjson.JSONObject;
import com.boomcat.boomcat.domain.*;
import com.boomcat.boomcat.service.ExpertService;
import com.boomcat.boomcat.util.JwtUtil;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@CrossOrigin("*")
@Component
@ServerEndpoint("/websocket/{token}")  // 注意不要以'/'结尾
public class WebSocketServer {
    final public static ConcurrentHashMap<Long, WebSocketServer> userSocketMap = new ConcurrentHashMap<>();
//    final public static ConcurrentHashMap<Long, WebSocketServer> expertSocketMap = new ConcurrentHashMap<>();
    final public static ConcurrentHashMap<Long, Long> match2 = new ConcurrentHashMap<>();

    private Session session = null;
    private  Long id=null;

    static public List<Long> getOnlineIds(){
        return userSocketMap.keySet().stream().toList();
    }

    // 注入专家列表
    private static ExpertService expertService;
    @Autowired
    public void setExpertService(ExpertService expertService) {
        WebSocketServer.expertService = expertService;
    }

    public List<Long> getExpertList(){
        //获取数据库内的专家列表
        return expertService.list().stream().map(Expert::getId).toList();
    }



    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) throws IOException {
        // 建立连接
        System.out.println("[COMMAND] connected!");
        this.session = session;

        try {
            id = JwtUtil.getUserId(token);
        }catch (Exception e) {
            // if not having userId, the one that I don't know
            //not you!
            System.out.println("[WARN] Checking Attack!!!");
            sendOneMessage("检测到恶意登入行为，请爱护网络环境，谢谢！！");
            this.session.close();
            return;
        }

        //判断连接者身份是用户还是专家 分开管理
        List<Long> expertIds = getExpertList();

        if (expertIds.contains(id)){
            userSocketMap.put(id,this);
        }else{
            userSocketMap.put(id, this);
        }

        System.out.println("当前在线用户列表：");
        userSocketMap.keySet().forEach(e->{
            System.out.println(e.longValue());
        });
//        System.out.println("当前在线专家列表：");
//        userSocketMap.keySet().forEach(e->{
//            System.out.println(e.longValue());
//        });
    }

    @OnClose
    public void onClose() {
        // 关闭链接
        System.out.println("[COMMAND] disconnected!");
        //断开连接的话要将user移除
        if (id != null) {
            List<Long> expertIds = getExpertList();
            if (expertIds.contains(id)){
                userSocketMap.remove(id);
            }else{
                userSocketMap.remove(id);
            }
        }

    }

    @OnMessage
    public void onMessage(String message, Session session) {
        // 从Client接收消息
        System.out.println("[COMMAND] 来自"+id+"的receive message!");
        System.out.println(message);
        JSONObject jsonObject = JSONObject.parseObject(message);
        String type=jsonObject.getString("type");

        switch (type){
            case "offer"->{
                Long to = jsonObject.getLong("to");
                if (!userSocketMap.containsKey(to)){
                    // 专家不在线
                    System.out.println("专家不在线");
                    JSONObject res=new JSONObject();
                    res.put("type","target not online");
                    sendOneMessage(res.toJSONString());
                }else{
                    JSONObject res=new JSONObject();
                    res.put("from",id);
                    res.put("type","offer");
                    res.put("offer",jsonObject.getJSONObject("offer"));
                    sendOneMessageTo(to,res.toJSONString());
                }
            }

            case "answer"->{

                // 接受来自谁的offer 现在返回给谁的answer
                Long from = jsonObject.getLong("from");
                // 应答 说明允许接通电话，那维持一个通话连接，方便交换candidate
                match2.put(from,id);
                match2.put(id,from);
                //
                JSONObject res=new JSONObject();
                res.put("from",id);
                res.put("type","answer");
                res.put("answer",jsonObject.getJSONObject("answer"));
                sendOneMessageTo(from,res.toJSONString());
            }

            case "ice-candidate"->{
                if (match2.containsKey(id)){
                    Long to=match2.get(id);
                    JSONObject res=new JSONObject();
                    res.put("from",id);
                    res.put("type","ice-candidate");
                    res.put("candidate",jsonObject.getJSONObject("candidate"));
                    sendOneMessageTo(to,res.toJSONString());
                }

            }

            default ->{
                System.out.println("出错了！！");
                JSONObject res=new JSONObject();
                res.put("type","msg err");
                sendOneMessage(res.toString());
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    //后端向前端发信息
    public void sendOneMessage(String message) {
        //异步通信要加上锁
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendOneMessageTo(Long to,String message) {
        //异步通信要加上锁
        synchronized (userSocketMap.get(to)) {
            try {
                userSocketMap.get(to).session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }




}